/*
Copyright © 2023 ywc 522350630@qq.com
*/
package cmd

import (
	"context"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	_ "gitee.com/yangwencheng/vblog/apps"
	"gitee.com/yangwencheng/vblog/config"
	"gitee.com/yangwencheng/vblog/ioc"
	"gitee.com/yangwencheng/vblog/logger"
	"gitee.com/yangwencheng/vblog/protocol"
	"gitee.com/yangwencheng/vblog/tracer"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cobra"
	"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
	"google.golang.org/grpc"
)

var (
	configType string
	configPath string
)

// serverCmd represents the server command
var serverCmd = &cobra.Command{
	Use:   "server",
	Short: "简短的命令描述 启动APP",
	Long:  `比较长的一个描述.`,
	Run: func(cmd *cobra.Command, args []string) {

		// 初始化配置文件
		var err error
		switch configType {
		case "file":
			_, err = config.GetConfigFromFile(configPath)
		case "env":
			_, err = config.GetConfigFromEnv()
		}
		cobra.CheckErr(err)

		tracer.InitTracer()
		r := gin.Default()
		r.Use(otelgin.Middleware("vblog"))
		httpServer := protocol.NewHttp(r)
		// 初始化控制器
		err = ioc.App().InitController()
		cobra.CheckErr(err)
		// 初始化api
		err = ioc.App().InitApi(r)
		cobra.CheckErr(err)

		grpcServer := grpc.NewServer()
		err = ioc.App().InitGrpc(grpcServer)
		cobra.CheckErr(err)

		// blog模块
		// blogImpl := impl.NewImpl()
		// blogImpl.Init()
		// blogHandle := api.NewHandler(blogImpl)
		// blogHandle.Register(r)
		// comment 模块
		// commentImpl := cimpl.NewImpl()
		// commentImpl.Init()
		// commentHandel := capi.NewHandel(commentImpl)
		// commentHandel.Register(r)

		go func() {
			herr := httpServer.Start()
			if herr != http.ErrServerClosed {
				cobra.CheckErr(herr)
			}
		}()
		//  启动GRPC server

		go func() {
			lis, err := net.Listen("tcp", ":1234")
			if err != nil {
				log.Fatal(err)
			}
			gerr := grpcServer.Serve(lis)
			cobra.CheckErr(gerr)
		}()

		// 信号处理 负责阻塞住主进行(Loop Os Signal)
		// 处理信号量
		ch := make(chan os.Signal, 1)
		// 如果os发出了信号后，会把该信号发往 ch channal
		signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP, syscall.SIGQUIT)

		// 从chanel中获取信号
		s := <-ch
		logger.GetLogger().Info().Msgf("receive os signal: %s, exit ...", s)

		// 做后续处理
		ctx := context.Background()
		httpServer.Stop(ctx)
		grpcServer.GracefulStop()
		// 其他资源释放逻辑
		//config.C().Mysql.db.Close()
	},
}

func init() {
	rootCmd.AddCommand(serverCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// serverCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
	serverCmd.Flags().StringVarP(&configType, "config-type", "t", "file", "程序加载配置的方式")
	serverCmd.Flags().StringVarP(&configPath, "config-path", "p", "etc", "配置文件的目录")
}
